const { resolve } = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const OptimizeCssAssetsWebpackPlugin = require('optimize-css-assets-webpack-plugin')

// 设置nodejs环境变量
process.env.NODE_ENV = 'production'

// 复用loader
const commonCssLoader = [
  // 这个loader取代style-loader。作用：提取js中的css成单独文件。优点：减少js体积，避免页面渲染闪频。
  {
    loader: MiniCssExtractPlugin.loader,
    options: {
      // 让css中所有地址都从上一级别找
      publicPath: '../'
    }
  },
  // 将css文件整合到js文件中
  'css-loader',
  /** css兼容性处理 postcss 依赖 postcss-loader postcss-preset-env
   * 识别对应的环境加载对应的配置
   * 该插件帮postcss找到package.json中browserslist里面的配置，通过配置加载指定的css兼容性样式
   * "browserslist": {
   *   // 开发环境，设置node环境变量：process.env.NODE_ENV = development
   *   "development": [
   *     "last 1 chrome version", // 兼容最近的一个chrome版本
   *     "last 1 firefox version",
   *     "last 1 safari version"
   *   ],
   *   // 生产环境：默认是生产环境
   *   "production": [
   *     ">0.2%", // 全球超过0.2%人使用的浏览器
   *     "not dead", // 不要已经丢弃的浏览器
   *     "not op_mini all" // 不要所有的欧朋浏览器
   *   ]
   * }
   */
  {
    loader: 'postcss-loader',
    options: {
      postcssOptions: {
        plugins: [
          'postcss-preset-env'
        ]
      }
    }
  }
]

module.exports = {
  entry: './src/js/index.js',
  output: {
    filename: 'js/built.js',
    path: resolve(__dirname, 'build')
  },
  module: {
    rules: [
      /**
       * 配置less css loader
       */
       {
        test: /\.css$/,
        use: [...commonCssLoader]
      },
      {
        test: /\.less$/,
        use: [...commonCssLoader, 'less-loader']
      },
      /** js语法检查 eslint-loader eslint
       * 注意：只检查自己写的源代码，第三方的库是不用检查的
       * 设置检查规则：
       *   package.json中eslintConfig中设置
       *    "eslintConfig": {
       *      "extends": "airbnb-base"
       *    }
       *  airbnb 需要依赖 eslint-config-airbnb-base eslint-plugin-import eslint
       * 
       * 一个文件只能被一个loader处理
       * 当一个文件要被多个loader处理，那么一定要指定loader执行的先后顺序: 先执行eslint 在执行babel  
       */ 
      {
        // 
        test: /\.js$/,
        exclude: /node_modules/,
        // 优先执行
        enforce: 'pre',
        loader: 'eslint-loader',
        options: {
          // 自动修复eslint的错误
          fix: true
        }
      },
      /** js兼容性处理 babel-loader @babel/core
       *  1.基本js兼容性处理 @babel/preset-env
       *    问题：只能转换基本语法，如promise高级语法不能转换
       *  2.全部js兼容性处理 @babel/polyfill  
       *    问题：我只要解决部分兼容性问题，但是将所有兼容性代码全部引入，体积太大了
       *  3.需要做兼容性处理的就做：按需加载 core-js
       */
      {
        test: /\.js$/,
        exclude: /node_modules/,
        loader: 'babel-loader',
        options: {
          // 预设: 指示babel做什么样的兼容性处理
          presets: [
            [
              '@babel/preset-env',
              {
                // 按需加载
                useBuiltIns: 'usage',
                // 指定core-js版本
                corejs: {
                  version: 3
                },
                // 指定兼容性到哪个版本浏览器
                targets: {
                  chrome: '60',
                  firefox: '60',
                  ie: '9',
                  safari: '10',
                  edge: '17'
                }
              }
            ]
          ]
        }
      },
      /**
       * 处理样式中图片，默认处理不了html中img图片
       * url-loader file-loader
       */
      {
        test: /\.(jpe?g|png|gif)$/,
        loader: 'url-loader',
        options: {
          // 图片大小小于8kb，就会被base64处理
          limit: 8 * 1024,
          // 给文件重命名：[hash:10]取图片的hash的前10位，[ext]取文件原来扩展名
          name: '[hash:10].[ext]',
          // 图片输出路径
          outputPath: 'imgs',
          // 关闭url-loader的es6模块化，使用commonjs解析
          esModule: false
        }
      },
      /**
       * 处理html文件的img图片：负责引入img，从而能被url-loader进行处理
       * html-loader
       */
      {
        test: /\.html$/,
        loader: 'html-loader',
        options: {
          esModule: false
        }
      },
      /**
       * 其他资源 file-loader
       */
      {
        exclude: /\.(js|css|less|html|jpg|png|gif)$/,
        loader: 'file-loader',
        options: {
          name: '[hash:10].[ext]',
          outputPath: 'media'
        }
      }
    ]
  },
  plugins: [
    new HtmlWebpackPlugin({
      //复制index.html文件，并自动引入打包输出所有的资源（js/css）
      template: './src/index.html',
      // 压缩html代码
      minify: {
        // 移除空格
        collapseWhitespace: true,
        // 移除注释
        removeComments: true
      }
    }),
    // 从js中抽取css成单独文件
    new MiniCssExtractPlugin({
      // 对输出的css文件进行重命名
      filename: 'css/built.css'
    }),
    // 压缩css
    new OptimizeCssAssetsWebpackPlugin()
  ],
  mode: 'development',
  /**
   * 开发服务器 devServer: 用来自动化（自动化编译，自动化打开浏览器，自动刷新浏览器）
   * 特点：只会在内存中编译打包，不会有任何输出
   * 启动devServer指令为：npx webpack-dev-server
   * 
   * 问题：运行npx webpack-dev-server报错
   * 原因：webpack现在存在一个bug,最新版的webpack-dev-server 和最新版的webpack-cli并不兼容
   * 解决方法一:webpack-cli的版本降为3.3.12，解决方法二：使用npx webpack serve这个命令运行。
   */
  devServer: {
    // 项目构建的路径
    contentBase: resolve(__dirname, 'build'),
    // 启动gzip压缩
    compress: true,
    // 端口号
    port: 3000,
    // 自动打开浏览器
    open: true
  }
}